
package com.gitee.jmash.storage.grpc;


import com.gitee.jmash.storage.entity.StorageOrganBrowserEntity;
import com.gitee.jmash.storage.mapper.StorageOrganBrowserMapper;
import com.gitee.jmash.storage.service.StorageOrganBrowserWrite;
import com.google.protobuf.Int32Value;
import java.util.List;
import java.util.Map;
import jmash.storage.protobuf.StorageOrganBrowserModel;
import jmash.storage.protobuf.StorageOrganBrowserUpdateReq;
import jmash.storage.protobuf.StorageOrganInfoUpdateReq;
import jmash.storage.protobuf.StorageOrganKey;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.shiro.authz.annotation.Logical;
import org.apache.shiro.authz.annotation.RequiresAuthentication;
import org.apache.shiro.authz.annotation.RequiresRoles;
import com.gitee.jmash.common.grpc.GrpcContext;
import com.gitee.jmash.common.security.JmashPrincipal;
import com.gitee.jmash.common.utils.UUIDUtil;
import com.gitee.jmash.common.utils.VersionUtil;
import com.gitee.jmash.core.grpc.cdi.GrpcService;
import com.gitee.jmash.core.lib.ProtoEnumUtil;
import com.gitee.jmash.core.orm.DtoPage;
import com.gitee.jmash.core.orm.DtoTotal;
import com.gitee.jmash.core.utils.LogbackUtils;
import com.gitee.jmash.storage.StorageFactory;
import com.gitee.jmash.storage.entity.StorageOrganInfoEntity;
import com.gitee.jmash.storage.entity.StorageOrganUserEntity;
import com.gitee.jmash.storage.entity.StorageOrganUserEntity.StorageOrganUserPk;
import com.gitee.jmash.storage.mapper.StorageOrganInfoMapper;
import com.gitee.jmash.storage.mapper.StorageOrganUserMapper;
import com.gitee.jmash.storage.service.StorageOrganInfoRead;
import com.gitee.jmash.storage.service.StorageOrganInfoWrite;
import com.gitee.jmash.storage.service.StorageOrganUserRead;
import com.gitee.jmash.storage.service.StorageOrganUserWrite;
import com.google.protobuf.BoolValue;
import com.google.protobuf.Empty;
import com.google.protobuf.EnumValue;
import com.google.protobuf.StringValue;
import io.grpc.Status;
import io.grpc.stub.StreamObserver;
import jmash.protobuf.CustomEnumValue;
import jmash.protobuf.CustomEnumValueMap;
import jmash.protobuf.Entry;
import jmash.protobuf.EntryList;
import jmash.protobuf.EnumEntryReq;
import jmash.protobuf.EnumValueList;
import jmash.protobuf.LogLevelReq;
import jmash.storage.protobuf.MyStorageOrganDefaultReq;
import jmash.storage.protobuf.MyStorageOrganReq;
import jmash.storage.protobuf.StorageOrganInfoCreateReq;
import jmash.storage.protobuf.StorageOrganInfoEnableKey;
import jmash.storage.protobuf.StorageOrganInfoKey;
import jmash.storage.protobuf.StorageOrganInfoList;
import jmash.storage.protobuf.StorageOrganInfoModel;
import jmash.storage.protobuf.StorageOrganInfoPage;
import jmash.storage.protobuf.StorageOrganInfoReq;
import jmash.storage.protobuf.StorageOrganUserCreateReq;
import jmash.storage.protobuf.StorageOrganUserKey;
import jmash.storage.protobuf.StorageOrganUserModel;

/**
 * Grpc服务实现.
 */
@GrpcService
public class StorageImpl extends jmash.storage.StorageGrpc.StorageImplBase {

  private static Log log = LogFactory.getLog(StorageImpl.class);

  // 模块版本
  public static final String version = "v1.0.0";

  @Override
  public void version(Empty request, StreamObserver<StringValue> responseObserver) {
    responseObserver
        .onNext(StringValue.of(version + "-" + VersionUtil.snapshot(StorageImpl.class)));
    responseObserver.onCompleted();
  }

  @Override
  public void findEnumList(StringValue request, StreamObserver<EnumValueList> responseObserver) {
    try {
      List<EnumValue> list = ProtoEnumUtil.getEnumList(request.getValue());
      responseObserver.onNext(EnumValueList.newBuilder().addAllValues(list).build());
      responseObserver.onCompleted();
    } catch (Exception ex) {
      log.error("", ex);
      responseObserver.onError(Status.INTERNAL.withDescription(ex.getMessage()).asException());
    }
  }

  @Override
  public void findEnumMap(StringValue request,
      StreamObserver<CustomEnumValueMap> responseObserver) {
    try {
      Map<Integer, CustomEnumValue> values = ProtoEnumUtil.getEnumMap(request.getValue());
      responseObserver.onNext(CustomEnumValueMap.newBuilder().putAllValues(values).build());
      responseObserver.onCompleted();
    } catch (Exception ex) {
      log.error("", ex);
      responseObserver.onError(Status.INTERNAL.withDescription(ex.getMessage()).asException());
    }
  }

  @Override
  public void findEnumEntry(EnumEntryReq request, StreamObserver<EntryList> responseObserver) {
    try {
      List<Entry> entryList =
          ProtoEnumUtil.getEnumCodeList(request.getClassName(), request.getType());
      responseObserver.onNext(EntryList.newBuilder().addAllValues(entryList).build());
      responseObserver.onCompleted();
    } catch (Exception ex) {
      log.error("", ex);
      responseObserver.onError(Status.INTERNAL.withDescription(ex.getMessage()).asException());
    }
  }

  @Override
  @RequiresAuthentication
  public void updateLogLevel(LogLevelReq request, StreamObserver<BoolValue> responseObserver) {
    LogbackUtils.updateLevel(request);
    LogbackUtils.testLog(request);
    responseObserver.onNext(BoolValue.of(true));
    responseObserver.onCompleted();
  }

  @Override
  @RequiresAuthentication
  public void updateStorageOrganBrowser(StorageOrganBrowserUpdateReq request,
      StreamObserver<StorageOrganBrowserModel> responseObserver) {
    try (StorageOrganBrowserWrite storageOrganBrowserWrite = StorageFactory.getStorageOrganBrowserWrite(
        request.getTenant())) {
      StorageOrganBrowserEntity entity = storageOrganBrowserWrite.update(request);
      StorageOrganBrowserModel model = StorageOrganBrowserMapper.INSTANCE.model(entity);
      responseObserver.onNext(model);
      responseObserver.onCompleted();
    } catch (Exception ex) {
      log.error("", ex);
      responseObserver.onError(Status.INTERNAL.withDescription(ex.getMessage()).asException());
    }
  }

  @Override
  @RequiresAuthentication
  public void findMyStorageOrganBrowseList(MyStorageOrganReq request,
      StreamObserver<StorageOrganInfoList> responseObserver) {
    JmashPrincipal p = GrpcContext.getPrincipal();
    try (StorageOrganInfoRead storageOrganInfoRead =
        StorageFactory.getStorageOrganInfoRead(request.getTenant())) {
      List<StorageOrganInfoEntity> list = storageOrganInfoRead
          .findMyStorageOrganBrowseList(request.getServiceTypeList(), p.getUnifiedId());
      List<StorageOrganInfoModel> modelList =
          StorageOrganInfoMapper.INSTANCE.listStorageOrganInfo(list);
      responseObserver.onNext(StorageOrganInfoList.newBuilder().addAllResults(modelList).build());
      responseObserver.onCompleted();
    } catch (Exception ex) {
      log.error("", ex);
      responseObserver.onError(Status.INTERNAL.withDescription(ex.getMessage()).asException());
    }
  }

  @Override
  @RequiresAuthentication
  public void findMyStorageOrganList(MyStorageOrganReq request,
      StreamObserver<StorageOrganInfoList> responseObserver) {
    JmashPrincipal p = GrpcContext.getPrincipal();
    try (StorageOrganInfoRead storageOrganInfoRead =
        StorageFactory.getStorageOrganInfoRead(request.getTenant())) {
      List<StorageOrganInfoEntity> list = storageOrganInfoRead
          .findMyStorageOrganList(request.getServiceTypeList(), p.getUnifiedId());
      List<StorageOrganInfoModel> modelList =
          StorageOrganInfoMapper.INSTANCE.listStorageOrganInfo(list);
      responseObserver.onNext(StorageOrganInfoList.newBuilder().addAllResults(modelList).build());
      responseObserver.onCompleted();
    } catch (Exception ex) {
      log.error("", ex);
      responseObserver.onError(Status.INTERNAL.withDescription(ex.getMessage()).asException());
    }
  }

  @Override
  @RequiresAuthentication
  public void findMyDefaultStorageOrgan(MyStorageOrganReq request,
      StreamObserver<StorageOrganInfoModel> responseObserver) {
    JmashPrincipal p = GrpcContext.getPrincipal();
    try (StorageOrganInfoRead storageOrganInfoRead =
        StorageFactory.getStorageOrganInfoRead(request.getTenant())) {
      StorageOrganInfoEntity entity = storageOrganInfoRead
          .findMyDefaultStorageOrgan(request.getServiceTypeList(), p.getUnifiedId());
      StorageOrganInfoModel model = StorageOrganInfoMapper.INSTANCE.model(entity);
      responseObserver.onNext(model);
      responseObserver.onCompleted();
    } catch (Exception ex) {
      log.error("", ex);
      responseObserver.onError(Status.INTERNAL.withDescription(ex.getMessage()).asException());
    }
  }

  @Override
  @RequiresAuthentication
  public void defaultMyStorageOrgan(MyStorageOrganDefaultReq request,
      StreamObserver<StorageOrganInfoModel> responseObserver) {
    try (
        StorageOrganUserWrite storageOrganUserWrite =
            StorageFactory.getStorageOrganUserWrite(request.getTenant());
        StorageOrganInfoRead storageOrganInfoRead =
            StorageFactory.getStorageOrganInfoRead(request.getTenant())) {
      StorageOrganUserEntity entity =
          storageOrganUserWrite.setMyDefaultOrgan(UUIDUtil.fromString(request.getOrganId()));
      StorageOrganInfoEntity model =
          storageOrganInfoRead.findOrganService(entity.getOrganId(), request.getServiceType());
      StorageOrganInfoModel info = StorageOrganInfoMapper.INSTANCE.model(model);
      responseObserver.onNext(info);
      responseObserver.onCompleted();
    } catch (Exception ex) {
      log.error("", ex);
      responseObserver.onError(Status.INTERNAL.withDescription(ex.getMessage()).asException());
    }
  }

  @Override
  @RequiresAuthentication
  public void findStorageOrganInfoPage(StorageOrganInfoReq request,
      StreamObserver<StorageOrganInfoPage> responseObserver) {
    try (StorageOrganInfoRead storageOrganInfoRead =
        StorageFactory.getStorageOrganInfoRead(request.getTenant())) {
      DtoPage<StorageOrganInfoEntity, DtoTotal> page = storageOrganInfoRead.findPageByReq(request);
      StorageOrganInfoPage modelPage = StorageOrganInfoMapper.INSTANCE.pageStorageOrganInfo(page);
      responseObserver.onNext(modelPage);
      responseObserver.onCompleted();
    } catch (Exception ex) {
      log.error("", ex);
      responseObserver.onError(Status.INTERNAL.withDescription(ex.getMessage()).asException());
    }
  }

  @Override
  @RequiresAuthentication
  public void findStorageOrganInfoList(StorageOrganInfoReq request,
      StreamObserver<StorageOrganInfoList> responseObserver) {
    try (StorageOrganInfoRead storageOrganInfoRead =
        StorageFactory.getStorageOrganInfoRead(request.getTenant())) {
      List<StorageOrganInfoEntity> list = storageOrganInfoRead.findListByReq(request);
      List<StorageOrganInfoModel> modelList =
          StorageOrganInfoMapper.INSTANCE.listStorageOrganInfo(list);
      responseObserver.onNext(StorageOrganInfoList.newBuilder().addAllResults(modelList).build());
      responseObserver.onCompleted();
    } catch (Exception ex) {
      log.error("", ex);
      responseObserver.onError(Status.INTERNAL.withDescription(ex.getMessage()).asException());
    }
  }

  @Override
  @RequiresAuthentication
  public void findStorageOrganInfoById(StorageOrganInfoKey request,
      StreamObserver<StorageOrganInfoModel> responseObserver) {
    try (StorageOrganInfoRead storageOrganInfoRead =
        StorageFactory.getStorageOrganInfoRead(request.getTenant())) {
      StorageOrganInfoEntity entity =
          storageOrganInfoRead.findById(UUIDUtil.fromString(request.getStorageId()));
      StorageOrganInfoModel model = StorageOrganInfoMapper.INSTANCE.model(entity);
      responseObserver.onNext(model);
      responseObserver.onCompleted();
    } catch (Exception ex) {
      log.error("", ex);
      responseObserver.onError(Status.INTERNAL.withDescription(ex.getMessage()).asException());
    }
  }

  @Override
  @RequiresRoles(value = {"system", "admin", "organ"}, logical = Logical.OR)
  public void createStorageOrganInfo(StorageOrganInfoCreateReq request,
      StreamObserver<StorageOrganInfoModel> responseObserver) {
    try (StorageOrganInfoWrite storageOrganInfoWrite =
        StorageFactory.getStorageOrganInfoWrite(request.getTenant())) {
      StorageOrganInfoEntity entity = storageOrganInfoWrite.insert(request);
      StorageOrganInfoModel model = StorageOrganInfoMapper.INSTANCE.model(entity);
      responseObserver.onNext(model);
      responseObserver.onCompleted();
    } catch (Exception ex) {
      log.error("", ex);
      responseObserver.onError(Status.INTERNAL.withDescription(ex.getMessage()).asException());
    }
  }

  @Override
  @RequiresRoles(value = {"system", "admin", "organ"}, logical = Logical.OR)
  public void updateStorageOrganInfo(StorageOrganInfoUpdateReq request,
                                     StreamObserver<StorageOrganInfoModel> responseObserver) {
    try (StorageOrganInfoWrite storageOrganInfoWrite =
             StorageFactory.getStorageOrganInfoWrite(request.getTenant())) {
      StorageOrganInfoEntity entity = storageOrganInfoWrite.update(request);
      StorageOrganInfoModel model = StorageOrganInfoMapper.INSTANCE.model(entity);
      responseObserver.onNext(model);
      responseObserver.onCompleted();
    } catch (Exception ex) {
      log.error("", ex);
      responseObserver.onError(Status.INTERNAL.withDescription(ex.getMessage()).asException());
    }
  }

  @Override
  @RequiresRoles(value = {"system", "admin", "organ"}, logical = Logical.OR)
  public void enableStorageOrganInfo(StorageOrganInfoEnableKey request,
      StreamObserver<BoolValue> responseObserver) {
    try (StorageOrganInfoWrite storageOrganInfoWrite =
        StorageFactory.getStorageOrganInfoWrite(request.getTenant())) {
      boolean value = storageOrganInfoWrite.enable(request);
      responseObserver.onNext(BoolValue.of(value));
      responseObserver.onCompleted();
    } catch (Exception ex) {
      log.error("", ex);
      responseObserver.onError(Status.INTERNAL.withDescription(ex.getMessage()).asException());
    }
  }

  @Override
  @RequiresRoles(value = {"system", "admin", "organ"}, logical = Logical.OR)
  public void deleteStorageOrganInfo(StorageOrganInfoKey request,
                                     StreamObserver<StorageOrganInfoModel> responseObserver) {
    try (StorageOrganInfoWrite storageOrganInfoWrite =
             StorageFactory.getStorageOrganInfoWrite(request.getTenant())) {
      StorageOrganInfoEntity entity =
          storageOrganInfoWrite.delete(UUIDUtil.fromString(request.getStorageId()));
      StorageOrganInfoModel model = StorageOrganInfoMapper.INSTANCE.model(entity);
      responseObserver.onNext(model);
      responseObserver.onCompleted();
    } catch (Exception ex) {
      log.error("", ex);
      responseObserver.onError(Status.INTERNAL.withDescription(ex.getMessage()).asException());
    }
  }

  @Override
  @RequiresRoles(value = {"system", "admin", "organ"}, logical = Logical.OR)
  public void deleteStorageOrgan(StorageOrganKey request,
                                 StreamObserver<Int32Value> responseObserver) {
    try (StorageOrganInfoWrite storageOrganInfoWrite =
             StorageFactory.getStorageOrganInfoWrite(request.getTenant())) {
      int i = storageOrganInfoWrite.deleteByIdAndType(request);
      responseObserver.onNext(Int32Value.of(i));
      responseObserver.onCompleted();
    } catch (Exception ex) {
      log.error("", ex);
      responseObserver.onError(Status.INTERNAL.withDescription(ex.getMessage()).asException());
    }
  }

  @Override
  public void existStorageOrganUser(StorageOrganUserKey request,
      StreamObserver<BoolValue> responseObserver) {
    try (StorageOrganUserRead storageOrganUserRead =
        StorageFactory.getStorageOrganUserRead(request.getTenant())) {
      StorageOrganUserPk pk = StorageOrganUserMapper.INSTANCE.pk(request);
      StorageOrganUserEntity entity = storageOrganUserRead.findById(pk);
      StorageOrganUserModel model = StorageOrganUserMapper.INSTANCE.model(entity);
      responseObserver.onNext(BoolValue.of(model != null));
      responseObserver.onCompleted();
    } catch (Exception ex) {
      log.error("", ex);
      responseObserver.onError(Status.INTERNAL.withDescription(ex.getMessage()).asException());
    }
  }

  @Override
  @RequiresRoles(value = {"system", "admin", "organ"}, logical = Logical.OR)
  public void createStorageOrganUser(StorageOrganUserCreateReq request,
      StreamObserver<StorageOrganUserModel> responseObserver) {
    try (StorageOrganUserWrite storageOrganUserWrite =
        StorageFactory.getStorageOrganUserWrite(request.getTenant())) {
      StorageOrganUserEntity entity = storageOrganUserWrite.insert(request);
      StorageOrganUserModel model = StorageOrganUserMapper.INSTANCE.model(entity);
      responseObserver.onNext(model);
      responseObserver.onCompleted();
    } catch (Exception ex) {
      log.error("", ex);
      responseObserver.onError(Status.INTERNAL.withDescription(ex.getMessage()).asException());
    }
  }

  @Override
  @RequiresRoles(value = {"system", "admin", "organ"}, logical = Logical.OR)
  public void deleteStorageOrganUser(StorageOrganUserKey request,
      StreamObserver<StorageOrganUserModel> responseObserver) {
    try (StorageOrganUserWrite storageOrganUserWrite =
        StorageFactory.getStorageOrganUserWrite(request.getTenant())) {
      StorageOrganUserPk pk = StorageOrganUserMapper.INSTANCE.pk(request);
      StorageOrganUserEntity entity = storageOrganUserWrite.delete(pk);
      StorageOrganUserModel model = StorageOrganUserMapper.INSTANCE.model(entity);
      responseObserver.onNext(model);
      responseObserver.onCompleted();
    } catch (Exception ex) {
      log.error("", ex);
      responseObserver.onError(Status.INTERNAL.withDescription(ex.getMessage()).asException());
    }
  }


}
